package com.branches.imgs;

import net.coobird.thumbnailator.Thumbnails;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

/**
 * @author wujian
 * @date 2024/5/22
 */
public class CombineImage {
    /**
     * 图片最大像素。
     */
    private static final int IMAGE_PIXEL_MAX = 4096;

    /**
     * 图片最小边长
     */
    private static final int IMAGE_PIXEL_MIN = 15;

    /**
     * 图片大小.
     */
    private static final int IMAGE_SIZE_MB = 6291456;

    private static final int PADDING_PIXEL = 100;

    private boolean isValid;

    private long id;

    public CombineImage() {
        this.items = new ArrayList<>();
        isValid = true;
    }

    private List<CombineItem> items;

    private BufferedImage file;

    public BufferedImage getFile() {
        return file;
    }

    public void setFile(BufferedImage file) {
        this.file = file;
    }

    public List<CombineItem> getItems() {
        return items;
    }

    public void setItems(List<CombineItem> items) {
        this.items = items;
    }

    public boolean checkSize(File file) {
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(file);
            byte[] fileBytes = new byte[(int) file.length()];
            if (file.length() > IMAGE_SIZE_MB) {
                return false;
            }
            try {
                fileInputStream.read(fileBytes);
                String base64Encoded = Base64.getEncoder().encodeToString(fileBytes);
                fileInputStream.close();
                boolean v = base64Encoded.length() < IMAGE_SIZE_MB;
                return v;
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return false;
    }

    // 拼接图片逻辑
    public boolean addItemOnX(OCRExamItem item) {
        try {
            CombineItem combineItem = new CombineItem();
            combineItem.setOcrExamItem(item);
            BufferedImage image = Thumbnails.of(item.getFile()).size(item.getWidth(), item.getHeight()).asBufferedImage();
            combineItem.setWidth(item.getWidth());
            combineItem.setHeight(item.getHeight());

            if (file == null) {
                // 将图片绘制上去
                // 绘制白纸。
                file = getBlankImage(item.getWidth(), item.getHeight());
                file.getGraphics().drawImage(image, 0, 0, null);
                combineItem.setX(0);
                combineItem.setY(0);
                items.add(combineItem);
                return true;
            } else {
                // 满足横向拼接
                int fw = file.getWidth();
                int fh = file.getHeight();
                if ((fw + item.getWidth() + PADDING_PIXEL) < IMAGE_PIXEL_MAX
                 && item.getHeight() < IMAGE_PIXEL_MAX) {
                    BufferedImage blankImage = getBlankImage(fw + item.getWidth() + PADDING_PIXEL, Math.max(fh, item.getHeight()));
                    blankImage.getGraphics().drawImage(file, 0, 0, fw, fh, null);
                    blankImage.getGraphics().drawImage(image, fw + PADDING_PIXEL, 0, image.getWidth(), image.getHeight(), null);
                    file = blankImage;
                    combineItem.setX(fw + PADDING_PIXEL);
                    combineItem.setY(0);
                    items.add(combineItem);
                    return true;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public boolean addItemOnY(CombineImage image) {
        int fw = file.getWidth();
        int fh = file.getHeight();
        if ((fh +  image.getFile().getHeight() + PADDING_PIXEL) < IMAGE_PIXEL_MAX
                &&  image.getFile().getWidth() < IMAGE_PIXEL_MAX) {
            BufferedImage blankImage = getBlankImage(Math.max(fw, image.getFile().getWidth()), fh + image.getFile().getHeight() + PADDING_PIXEL);
            blankImage.getGraphics().drawImage(file, 0, 0, fw, fh, null);
            blankImage.getGraphics().drawImage(image.getFile(), 0, fh + PADDING_PIXEL, image.file.getWidth(), image.file.getHeight(), null);
            image.setValid(false);
            file = blankImage;
            image.getItems().forEach(combineItem -> {
                combineItem.setY(fh + PADDING_PIXEL);
            });

            this.getItems().addAll(image.getItems());

            return true;
        }
        return false;
    }

    private BufferedImage getBlankImage(int w, int h) {
        BufferedImage file = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < file.getWidth(); x++) {
            for (int y = 0; y < file.getHeight(); y++) {
                file.setRGB(x, y, Color.WHITE.getRGB());
            }
        }
        return file;
    }

    public boolean isValid() {
        return isValid;
    }

    public void setValid(boolean valid) {
        isValid = valid;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }
}
